package com.yehebl.orm.data.map;

import com.yehebl.orm.data.common.IDao;
import com.yehebl.orm.data.common.dto.Page;
import com.yehebl.orm.data.common.dto.SimplePage;
import com.yehebl.orm.data.lambda.PropertyFun;
import com.yehebl.orm.util.LambdaUtil;

import java.util.*;

/**
 * 表达式解析
 */
public class ExpressionMap extends HashMap<String, Object> {
    public ExpressionMap(IDao dao) {
        this.dao = dao;
    }

    private static final long serialVersionUID = 1L;


    private int orderIndex = 0;

    private final IDao dao;

    private Integer page;

    private Integer size;


    /**
     * 分页类型 null或者1:分页和数据,2:数据,3:分页
     */
    private Integer pageType;

    /**
     * 只更新这些字段
     */
    private Set<String> updateSetField;

    /**
     * 过滤这些字段
     */
    private Set<String> updateSetFilterField;


    /**
     * 等于
     */
    public ExpressionMap eq(String field, Object obj) {
        if (obj == null) {
            return this;
        }
        if (obj instanceof String && "".equals(obj.toString().trim())) {
            return this;
        }
        this.put("EQ_" + field, obj);
        return this;
    }

    public <T, R> ExpressionMap eq(PropertyFun<T, R> column, Object obj) {
        String columnName = LambdaUtil.getPropertyName(column);
        return eq(columnName, obj);
    }

    private Set<String> getUpdateSetField() {
        if (updateSetField == null) {
            updateSetField = new HashSet<>();
        }
        return updateSetField;
    }

    private Set<String> getUpdateSetFilterField() {
        if (updateSetFilterField == null) {
            updateSetFilterField = new HashSet<>();
        }
        return updateSetFilterField;
    }

    public <T, R> ExpressionMap set(PropertyFun<T, R> column) {
        String columnName = LambdaUtil.getPropertyName(column);
        getUpdateSetField().add(columnName);
        return this;
    }

    public <T, R> ExpressionMap set(String field) {
        getUpdateSetField().add(field);
        return this;
    }


    public <T, R> ExpressionMap noSet(PropertyFun<T, R> column) {
        String columnName = LambdaUtil.getPropertyName(column);
        getUpdateSetFilterField().add(columnName);
        return this;
    }

    public <T, R> ExpressionMap noSet(String field) {
        getUpdateSetFilterField().add(field);
        return this;
    }

    /**
     * in查询 逗号分隔
     */
    public ExpressionMap in(String field, Object[] obj) {
        if (obj == null) {
            return this;
        }
        this.put("IN_" + field, obj);
        return this;
    }

    public <T, R> ExpressionMap in(PropertyFun<T, R> column, Object[] obj) {
        String columnName = LambdaUtil.getPropertyName(column);
        return in(columnName, obj);
    }


    /**
     * not in查询 逗号分隔
     */
    public ExpressionMap nin(String field, Object[] obj) {
        if (obj == null) {
            return this;
        }
        this.put("NIN_" + field, obj);
        return this;
    }

    public <T, R> ExpressionMap nin(PropertyFun<T, R> column, Object[] obj) {
        String columnName = LambdaUtil.getPropertyName(column);
        return nin(columnName, obj);
    }

    /**
     * in查询 逗号分隔
     */
    public ExpressionMap in(String field, Collection<?> obj) {
        if (obj == null) {
            return this;
        }
        this.put("IN_" + field, obj);
        return this;
    }

    public <T, R> ExpressionMap in(PropertyFun<T, R> column, Collection<?> obj) {
        String columnName = LambdaUtil.getPropertyName(column);
        return in(columnName, obj);
    }

    /**
     * not in查询 逗号分隔
     */
    public ExpressionMap nin(String field, Collection<?> obj) {
        if (obj == null) {
            return this;
        }
        this.put("NIN_" + field, obj);
        return this;
    }

    public <T, R> ExpressionMap nin(PropertyFun<T, R> column, Collection<?> obj) {
        String columnName = LambdaUtil.getPropertyName(column);
        return nin(columnName, obj);
    }

    /**
     * 等于
     */
    public ExpressionMap eqIsBlank(String field, Object obj) {
        this.put("EQ_" + field, obj);
        return this;
    }

    /**
     * 等于 允许为空串或者null
     */
    public <T, R> ExpressionMap eqIsBlank(PropertyFun<T, R> column, Object obj) {
        String columnName = LambdaUtil.getPropertyName(column);
        return eqIsBlank(columnName, obj);
    }

    /**
     * 不等于
     */
    public ExpressionMap neq(String field, Object obj) {
        if (obj == null) {
            return this;
        }
        if (obj instanceof String && "".equals(obj.toString().trim())) {
            return this;
        }
        this.put("NEQ_" + field, obj);
        return this;
    }

    public <T, R> ExpressionMap neq(PropertyFun<T, R> column, Object obj) {
        String columnName = LambdaUtil.getPropertyName(column);
        return neq(columnName, obj);
    }

    /**
     * 不等于
     */
    public ExpressionMap neqIsBlank(String field, Object obj) {
        this.put("NEQ_" + field, obj);
        return this;
    }


    public <T, R> ExpressionMap neqIsBlank(PropertyFun<T, R> column, Object obj) {
        String columnName = LambdaUtil.getPropertyName(column);
        return neqIsBlank(columnName, obj);
    }

    /**
     * 小于
     */
    public ExpressionMap lt(String field, Object obj) {
        if (obj == null) {
            return this;
        }
        if (obj instanceof String && "".equals(obj.toString().trim())) {
            return this;
        }
        this.put("LT_" + field, obj);
        return this;
    }


    /**
     * 小于
     */
    public ExpressionMap ltIsBlank(String field, Object obj) {
        this.put("LT_" + field, obj);
        return this;
    }
    public <T, R> ExpressionMap lt(PropertyFun<T, R> column, Object obj) {
        String columnName = LambdaUtil.getPropertyName(column);
        return lt(columnName, obj);
    }

    public <T, R> ExpressionMap ltIsBlank(PropertyFun<T, R> column, Object obj) {
        String columnName = LambdaUtil.getPropertyName(column);
        return ltIsBlank(columnName, obj);
    }

    /**
     * 大于
     */
    public ExpressionMap gt(String field, Object obj) {
        if (obj == null) {
            return this;
        }
        if (obj instanceof String && "".equals(obj.toString().trim())) {
            return this;
        }
        this.put("GT_" + field, obj);
        return this;
    }
    /**
     * 大于
     */
    public ExpressionMap gtIsBlank(String field, Object obj) {
        this.put("GT_" + field, obj);
        return this;
    }

    public <T, R> ExpressionMap gt(PropertyFun<T, R> column, Object obj) {
        String columnName = LambdaUtil.getPropertyName(column);
        return gt(columnName, obj);
    }

    public <T, R> ExpressionMap gtIsBlank(PropertyFun<T, R> column, Object obj) {
        String columnName = LambdaUtil.getPropertyName(column);
        return gtIsBlank(columnName, obj);
    }

    /**
     * 大于等于
     */
    public ExpressionMap geq(String field, Object obj) {
        if (obj == null) {
            return this;
        }
        if (obj instanceof String && "".equals(obj.toString().trim())) {
            return this;
        }
        this.put("GEQ_" + field, obj);
        return this;
    }

    /**
     * 大于等于
     */
    public ExpressionMap geqIsBlank(String field, Object obj) {
        this.put("GEQ_" + field, obj);
        return this;
    }

    public <T, R> ExpressionMap geq(PropertyFun<T, R> column, Object obj) {
        String columnName = LambdaUtil.getPropertyName(column);
        return geq(columnName, obj);
    }

    public <T, R> ExpressionMap geqIsBlank(PropertyFun<T, R> column, Object obj) {
        String columnName = LambdaUtil.getPropertyName(column);
        return geqIsBlank(columnName, obj);
    }
    /**
     * 小于等于
     */
    public ExpressionMap leq(String field, Object obj) {
        if (obj == null) {
            return this;
        }
        if (obj instanceof String && "".equals(obj.toString().trim())) {
            return this;
        }
        this.put("LEQ_" + field, obj);
        return this;
    }


    /**
     * 小于等于
     */
    public ExpressionMap leqIsBlank(String field, Object obj) {
        this.put("LEQ_" + field, obj);
        return this;
    }


    public <T, R> ExpressionMap leq(PropertyFun<T, R> column, Object obj) {
        String columnName = LambdaUtil.getPropertyName(column);
        return leq(columnName, obj);
    }

    public <T, R> ExpressionMap leqIsBlank(PropertyFun<T, R> column, Object obj) {
        String columnName = LambdaUtil.getPropertyName(column);
        return leqIsBlank(columnName, obj);
    }

    /**
     * 左右模糊查询
     */
    public ExpressionMap like(String field, Object obj) {
        if (obj == null) {
            return this;
        }
        if (obj instanceof String && "".equals(obj.toString().trim())) {
            return this;
        }
        this.put("LIKE_" + field, obj);
        return this;
    }


    /**
     * 左右模糊查询
     */
    public ExpressionMap likeIsBlank(String field, Object obj) {
        this.put("LIKE_" + field, obj);
        return this;
    }

    public <T, R> ExpressionMap like(PropertyFun<T, R> column, Object obj) {
        String columnName = LambdaUtil.getPropertyName(column);
        return like(columnName, obj);
    }

    public <T, R> ExpressionMap likeIsBlank(PropertyFun<T, R> column, Object obj) {
        String columnName = LambdaUtil.getPropertyName(column);
        return likeIsBlank(columnName, obj);
    }


    /**
     * 左模糊查询
     */
    public ExpressionMap llike(String field, Object obj) {
        if (obj == null) {
            return this;
        }
        if (obj instanceof String && "".equals(obj.toString().trim())) {
            return this;
        }
        this.put("LLIKE_" + field, obj);
        return this;
    }

    /**
     * 左模糊查询
     */
    public ExpressionMap llikeIsBlank(String field, Object obj) {
        this.put("LLIKE_" + field, obj);
        return this;
    }


    public <T, R> ExpressionMap llike(PropertyFun<T, R> column, Object obj) {
        String columnName = LambdaUtil.getPropertyName(column);
        return llike(columnName, obj);
    }

    public <T, R> ExpressionMap llikeIsBlank(PropertyFun<T, R> column, Object obj) {
        String columnName = LambdaUtil.getPropertyName(column);
        return llikeIsBlank(columnName, obj);
    }
    /**
     * 右模糊查询
     */
    public ExpressionMap rlike(String field, Object obj) {
        if (obj == null) {
            return this;
        }
        if (obj instanceof String && "".equals(obj.toString().trim())) {
            return this;
        }
        this.put("RLIKE_" + field, obj);
        return this;
    }

    /**
     * 右模糊查询
     */
    public ExpressionMap rlikeIsBlank(String field, Object obj) {
        this.put("RLIKE_" + field, obj);
        return this;
    }


    public <T, R> ExpressionMap rlike(PropertyFun<T, R> column, Object obj) {
        String columnName = LambdaUtil.getPropertyName(column);
        return rlike(columnName, obj);
    }

    public <T, R> ExpressionMap rlikeIsBlank(PropertyFun<T, R> column, Object obj) {
        String columnName = LambdaUtil.getPropertyName(column);
        return rlikeIsBlank(columnName, obj);
    }
    /**
     * 倒序
     */
    public ExpressionMap orderDesc(String field) {
        if (field == null || "".equals(field.trim())) {
            return this;
        }
        this.put("ORDER_" + orderIndex + "_" + field, "desc");
        orderIndex++;
        return this;
    }

    public <T, R> ExpressionMap orderDesc(PropertyFun<T, R> column) {
        String columnName = LambdaUtil.getPropertyName(column);
        return orderDesc(columnName);
    }

    /**
     * 升序
     */
    public ExpressionMap order(String field) {
        if (field == null || "".equals(field.trim())) {
            return this;
        }
        this.put("ORDER_" + orderIndex + "_" + field, "asc");
        orderIndex++;
        return this;
    }

    public <T, R> ExpressionMap order(PropertyFun<T, R> column) {
        String columnName = LambdaUtil.getPropertyName(column);
        return order(columnName);
    }


    public ExpressionMap order(String field, String order) {
        if (field == null || "".equals(field.trim())) {
            return this;
        }
        if (order == null || "".equals(order.trim())) {
            order = "asc";
        }
        this.put("ORDER_" + orderIndex + "_" + field, order);
        orderIndex++;
        return this;
    }

    public <T, R> ExpressionMap order(PropertyFun<T, R> column, String order) {
        String columnName = LambdaUtil.getPropertyName(column);
        return order(columnName, order);
    }

    /**
     * 分页
     */
    public ExpressionMap limit(Integer page, Integer size) {
        this.put("PAGE", page < 1 ? 1 : page);
        this.put("SIZE", size);
        this.page = page;
        this.size = size;
        return this;
    }

    /**
     * @param pageType null或者1:分页和数据,2:数据,3:分页
     *                 分页
     */
    public ExpressionMap limit(Integer page, Integer size, Integer pageType) {
        this.put("PAGE", page < 1 ? 1 : page);
        this.put("SIZE", size);
        this.page = page;
        this.size = size;
        this.pageType = pageType;
        return this;
    }

    /**
     * 分页
     */
    public ExpressionMap limit(Page<?> page) {
        return limit(page.getPage(), page.getSize());
    }

    /**
     * 分页
     */
    public ExpressionMap limit(Integer size) {
        this.put("SIZE", size);
        return this;
    }

    /**
     * 查询list 列表
     */
    public <T> List<T> find(Class<T> clazz) {
        return dao.findByMap(this, clazz);
    }

    /**
     * 查询分页对象列表
     */
    public <T> Page<T> findPage(Class<T> clazz) {
        if (page == null || size == null) {
            throw new RuntimeException("page 或 size 不能为空");
        }
        return dao.findPageByMap(this.page, this.size, this.pageType, this, clazz);
    }


    /**
     * 查询分页对象列表,如果没有页码则使用线程绑定的Page对象，如果线程未绑定分页对象，则使用默认分页对象(1,10)
     */
    public <T> SimplePage<T> findSimplePage(Class<T> clazz) {
        if (page == null || size == null) {
            throw new RuntimeException("page 或 size 不能为空");
        }
        return dao.findSimplePageByMap(this.page, this.size, this, clazz);
    }

    /**
     * 查询单条数据
     */
    public <T> T get(Class<T> clazz) {
        return dao.getByMap(this, clazz);
    }

    /**
     * 统计条数
     */
    public <T> Integer getCount(Class<T> clazz) {
        return dao.getCountByMap(this, clazz);
    }

    /**
     * 查询第一条数据
     */
    public <T> T getOne(Class<T> clazz) {
        return dao.getOneByMap(this, clazz);
    }

    /**
     * 根据集合表达式条件删除对象
     */
    public <T> int delete(Class<T> clazz) {
        return dao.deleteByMap(this, clazz);
    }

    /**
     * 根据集合表达式条件更新对象
     */
    public int update(Object entity) {
        if(this.updateSetField!=null){
            return dao.updateByMap(entity,this, this.updateSetField);
        }
        if(this.updateSetFilterField!=null){
            return dao.updateFilterByMap(entity,this, this.updateSetFilterField);
        }
        return dao.updateByMap(entity, this);
    }

    /**
     * 根据集合表达式条件更新对象
     */
    public <T> int update(Object entity, String... updateField) {
        return dao.updateByMap(entity, this, updateField);
    }



    /**
     * 根据集合表达式条件更新对象
     *
     * @param entity      要更新的内容
     * @param filterField 不更新的字段
     * @return 影响条数
     */
    public <T> int updateFilter(Object entity, String... filterField) {
        return dao.updateFilterByMap(entity, this, filterField);
    }




}
